package com.safe.first.common.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Instant;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * @author Mickey
 * @since 2021/11/11
 */
@MapperScan("com.safe.first.**.mapper")
@Configuration
@AllArgsConstructor
public class MybatisPlusConfig {

    private final ObjectMapper objectMapper;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }


    @PostConstruct
    public void initJacksonTypeHandler() {
        JacksonTypeHandler.setObjectMapper(objectMapper);
    }

    @Slf4j
    @Component
    public static class MyMetaObjectHandler implements MetaObjectHandler {

        @Override
        public void insertFill(MetaObject metaObject) {
            Instant now = Instant.now();
            this.strictInsertFill(metaObject, "createdAt", () -> now, Instant.class);
            this.strictInsertFill(metaObject, "updatedAt", () -> now, Instant.class);

            //插入创建用户
//            Optional.ofNullable(BaseContextHandler.getUserId())
//                    .ifPresent(userId -> this.strictInsertFill(metaObject, "createBy", userId::toString, String.class));

        }

        @Override
        public void updateFill(MetaObject metaObject) {
            this.strictUpdateFill(metaObject, "updatedAt", Instant::now, Instant.class);

            //更新修用户
//            Optional.ofNullable(BaseContextHandler.getUserId())
//                    .ifPresent(userId -> this.strictInsertFill(metaObject, "updateBy", userId::toString, String.class));

        }

        /**
         * 目标属性不为空也替换
         *
         * @param metaObject
         * @param fieldName
         * @param fieldVal
         * @return
         */
        @Override
        public MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<?> fieldVal) {
            Object obj = fieldVal.get();
            if (Objects.nonNull(obj)) {
                metaObject.setValue(fieldName, obj);
            }
            return this;
        }
    }
}
